#ifndef __losor_ccpl_h__
#define __losor_ccpl_h__

#include <list.h>
#include <map.h>
#include <inttype.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _life
{
    long ref;
} life;

#define control_life()    life __$any_for_life_control$__


typedef struct _ppoutput
{
    list *tokens;
    list *comments;
    list *errors;
    smap *symbols;
    smap *types;
    list *ppcond;
} ppoutput;

typedef struct _code
{
    char *file;
    uint32 line;
    uint8 *code_buf;
} code ;

typedef struct _lex_info
{
    list *tokens;
    int cur_token;
    list *comments;
    int cur_comment;
    list *errors;
    smap *symbols;
} lex_info;

int32 preprocess( code* cd, ppoutput *out );

typedef enum _token_type
{
    KEYWORD,
    IDENTIFIER,
    CHARACTER,
    STRING,
    COMMENT,
    INTEGER,
    FLOATING,
    OPERATOR,

    PCT_COMMA = 1 << 16,
    PCT_ASSIGN,
    PCT_ASSIGN_MUL,
    PCT_ASSIGN_DEV,
    PCT_ASSIGN_MOD,
    PCT_ASSIGN_ADD,
    PCT_ASSIGN_SUB,
    PCT_ASSIGN_SHIFT_L,
    PCT_ASSIGN_SHIFT_R,
    PCT_ASSIGN_AND,
    PCT_ASSIGN_XOR,
    PCT_ASSIGN_OR,
    PCT_CONDITION,
    PCT_LOGICAL_OR,
    PCT_LOGICAL_AND,
    PCT_INCLUSIVE_OR,
    PCT_EXCLUSIVE_OR,
    PCT_AND,
    PCT_EQUAL,
    PCT_UNEQUAL,
    PCT_SMALL,
    PCT_LARGE,
    PCT_SMALL_EQUAL,
    PCT_LARGE_EQUAL,
    PCT_SHIFT_L,
    PCT_SHIFT_R,
    PCT_ADD,
    PCT_SUB,
    PCT_MUL,
    PCT_DEV,
    PCT_MOD,
    PCT_CAST,
    PCT_ADDRESS,
    PCT_VALUE,
    PCT_POSITIVE,
    PCT_NEGATIVE,
    PCT_NOT,
    PCT_LOGICAL_NOT,
    PCT_SIZEOF,
    PCT_ARRAY_L,
    PCT_ARRAY_R,
    PCT_CALL,
    PCT_DOT,
    PCT_POINT,
    PCT_INC_PRE,
    PCT_INC_POST,
    PCT_DEC_PRE,
    PCT_DEC_POST,
    PCT_PARENTHESES_L,
    PCT_PARENTHESES_R,

    KW_AUTO,
    KW_BREAK,
    KW_CASE,
    KW_CHAR,
    KW_CONST,
    KW_CONTINUE,
    KW_DEFAULT,
    KW_DO,
    KW_DOUBLE,
    KW_ELSE,
    KW_ENUM,
    KW_EXTERN,
    KW_FLOAT,
    KW_FOR,
    KW_GOTO,
    KW_IF,
    KW_INLINE,
    KW_INT,
    KW_LONG,
    KW_REGISTER,
    KW_RESTRICT,
    KW_RETURN,
    KW_SHORT,
    KW_SIGNED,
    KW_SIZEOF,
    KW_STATIC,
    KW_STRUCT,
    KW_SWITCH,
    KW_TYPEDEF,
    KW_UNION,
    KW_UNSIGNED,
    KW_VOID,
    KW_VOLATILE,
    KW_WHILE,
    KW_BOOL,
    KW_COMPLEX,
    KW_IMAGINARY,

} token_type;

typedef struct _token
{
    control_life();
    struct _exp_tree *ppcond;
    int type;
    void* attr;
    char *name;
    const char *file;
    uint32 line;
} token;

#define TOKEN_TYPE(toke)        (toke->type & 0xffff)
#define PCT_TYPE(toke)          (TOKEN_TYPE(toke)==OPERATOR ? (toke->type & 0xffff0000) : 0)
#define KW_TYPE(toke)           (TOKEN_TYPE(toke)==KEYWORD ? (toke->type & 0xffff0000) : 0)

int token_release( token *tk );
int tkcmp( token *t1, token *t2 );

typedef enum _syntype
{
    T_MACRO,
    T_VAR,
    T_FUNC,
    T_STRUCT,
    T_ENUM,
    T_UNION,
    T_TYPEDEF,

    T_SYSTEM,
    T_PACKAGE,
    T_FILE,
    T_CONST,
    T_LABEL,
} syntype;

typedef enum _base_type
{
    T_SIMPLE,
    T_POINT,
    T_ARRAY,
} base_type;

enum vartypeext
{
    VTE_EXTERN      = 1<<0,
    VTE_STATIC      = 1<<1,
    VTE_CONST       = 1<<2,
    VTE_AUTO        = 1<<3,
    VTE_REGISTER    = 1<<4,
    VTE_RESTRICT    = 1<<5,
    VTE_VOLATILE    = 1<<6,
    VTE_UNSIGNED    = 1<<7,
    VTE_BLONG       = 1<<8,
};

typedef struct _vartype
{
    control_life();
    base_type type;
    void *name;
    //     union{
    //         struct _symbol *st;
    //         struct _pointtype *pt;
    //         struct _arrtype *at;
    //     } name;
    int32 size;
    int32 ext;
} vartype;

typedef struct _pointtype
{
    vartype *base;
} pointtype;

typedef struct _arrtype
{
    vartype *base;
    int32 count;
} arrtype;

typedef struct _functype
{
    vartype* ret;
    list* para;
} functype;

typedef struct _structmem
{
    vartype *type;
    token *name;
} structmem;

typedef struct _structtype
{
    token* name;
    list* member;
} structtype;

typedef struct _uniontype
{
    token *name;
    list *member;
} uniontype;

typedef struct _enummember
{
    token* name;
    int32 val;
} enummember;

typedef struct _enumtype
{
    token *name;
    list *member;
} enumtype;

typedef struct _typedeftype
{
    token* name;
    vartype* ty;
} typedeftype;

typedef struct _macrotype
{
    token* name;
    int32 npara;
    list* rep;
    list* para;
} macrotype;

typedef struct _symtype
{
    control_life();
    syntype syn;
    void *attr;
    //     union{
    //         vartype *vt;
    //         functype *ft;
    //         structtype *st;
    //         uniontype *ut;
    //         enumtype *et;
    //         typedeftype *tt;
    //         macrotype *mt;
    //     } attr;
    int size;
} symtype;

int symtype_release( symtype *ty );
int vt_release( vartype *ty );
char* vt_name( const vartype *vt );
int macro_release( macrotype *mt );

typedef struct _exp_tree
{
    vartype *ret;
    token *opt;
    void *opd1, *opd2, *opd3;
} exp_tree;

int exp_tree_release( exp_tree* et );

typedef struct _symbol
{
    list *decl;
    symtype *type;
    token *name;
    struct _symbol *region;
    list *ref;
    list *beref;
} symbol;

symbol* sym_find( const char *name );
char* sym_name( symbol *sym, int full );
vartype* vt_find( const char *name );
int sym_release( symbol *sym );

extern symbol *syms;

#ifdef __cplusplus
};
#endif

#endif // __losor_ccpl_h__
